package gestordeentidades.gateways;

import entidades.DesenhoDinamico;
import entidades.Estilo;
import entidades.Familia;
import entidades.Rectangulo;
import gestordeentidades.identitymap.interfaces.IEntityMap;
import gestordeentidades.persistance.database.Converter;
import gestordeentidades.persistance.interfaces.IDataBaseAdapter;
import gestordeentidades.persistance.interfaces.IDataBaseRow;
import gestordeentidades.persistance.interfaces.IDataBaseStatement;
import gestordeentidades.persistance.interfaces.IGateway;
import gestordeentidades.persistance.interfaces.ILinha;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import entidades.Telha;
import entidades.TipoTelha;

/**
 * Trabalho DAS - 2014/2015
 * @author a21210380, a21190325, a21210392
 */
public class TelhaGateway implements IGateway<Telha> {
    private static final Logger logger = Logger.getLogger(TelhaGateway.class.getName());

    public static final String SQL_CREATE = "CREATE TABLE IF NOT EXISTS telha ("
            + "id " + Converter.convertToSqlText(int.class) + " NOT NULL,"
            + "id_familia " + Converter.convertToSqlText(int.class) + " NOT NULL,"
            + "id_estilo " + Converter.convertToSqlText(int.class) + " NOT NULL,"
            + "id_rectangulo " + Converter.convertToSqlText(int.class) + " NOT NULL,"
            + "id_desenho " + Converter.convertToSqlText(int.class) + " NOT NULL,"
            + "id_tipo_de_telha " + Converter.convertToSqlText(int.class) + " NOT NULL);";
    public static final String SQL_DROP = "DROP TABLE telha;";
    public static final String SQL_INSERT = "INSERT INTO telha VALUES (?,?,?,?,?,?);";
    public static final String SQL_UPDATE = "UPDATE telha SET id_familia=?,id_estilo=?,id_rectangulo=?,id_tipo_de_telha=?,id_desenho=? WHERE id=?;";
    public static final String SQL_DELETE = "DELETE FROM telha WHERE id=?;";
    public static final String SQL_FIND_BY_ID = "SELECT * FROM telha WHERE id=?;";
    public static final String SQL_FIND_ALL = "SELECT * FROM telha;";

    

    @Override
    public void initTable(IDataBaseAdapter dataBase) {
        dataBase.executarSql(SQL_CREATE);
    }

    @Override
    public void dropTable(IDataBaseAdapter dataBase) {
        dataBase.executarSql(SQL_DROP);
    }

    @Override
    public boolean inserirNovaEntidade(IDataBaseAdapter dataBase, Telha object) {
        IDataBaseStatement statement = dataBase.getDataBaseStatement(SQL_INSERT);
        statement.adicionarParametroSql(1, object.getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(2, object.getFamilia().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(3, object.getEstilo().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(4, object.getRectangulo().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(5, object.getDesenho().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(6, object.getTipoDeTelha().getId(), Converter.convertToSqlText(int.class));
        return (dataBase.inserir(statement) == 1);
    }

    @Override
    public boolean atualizarEntidade(IDataBaseAdapter dataBase, Telha object) {
        IDataBaseStatement statement = dataBase.getDataBaseStatement(SQL_UPDATE);
        statement.adicionarParametroSql(1, object.getFamilia().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(2, object.getEstilo().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(3, object.getRectangulo().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(4, object.getDesenho().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(5, object.getTipoDeTelha().getId(), Converter.convertToSqlText(int.class));
        statement.adicionarParametroSql(6, object.getId(), Converter.convertToSqlText(int.class));
        return (dataBase.atualizar(statement) == 1);
    }

    @Override
    public boolean apagarEntidade(IDataBaseAdapter dataBase, Telha object) {
        IDataBaseStatement statement = dataBase.getDataBaseStatement(SQL_DELETE);
        statement.adicionarParametroSql(1, object.getId(), Converter.convertToSqlText(int.class));
        return (dataBase.atualizar(statement) == 1);
    }

    @Override
    public Telha procurarEntidadePeloID(IDataBaseAdapter dataBase, IEntityMap entityMap, int id) {
        IDataBaseStatement statement = dataBase.getDataBaseStatement(SQL_FIND_BY_ID);
        statement.adicionarParametroSql(1, id, Converter.convertToSqlText(int.class));
        ProcurarPorID p = new ProcurarPorID(entityMap);
        dataBase.ler(statement, p);
        return p.getTelha();
    }

    @Override
    public Map<Integer, Telha> procurarPorTodasAsEntidadesComoMapa(IDataBaseAdapter dataBase, IEntityMap entityMap) {
        IDataBaseStatement statement = dataBase.getDataBaseStatement(SQL_FIND_ALL);
        ProcurarComoMapa p = new ProcurarComoMapa(entityMap);
        dataBase.ler(statement, p);
        return p.getTelhas();
    }
    
    private class ProcurarPorID implements IDataBaseRow {
        private final IEntityMap entityMap;
        private Telha telha = null;
        
        ProcurarPorID(IEntityMap entityMap) {
            this.entityMap = entityMap;
        }

        public Telha getTelha() {
            return telha;
        }

        @Override
        public void onLinhaLida(ILinha linha) {
            int id = linha.getInt("id");
            int id_familia = linha.getInt("id_familia");
            int id_estilo = linha.getInt("id_estilo");
            int id_rectangulo = linha.getInt("id_rectangulo");
            int id_desenho = linha.getInt("id_desenho");
            int id_tipo_de_telha = linha.getInt("id_tipo_de_telha");
            
            Telha t = new Telha(
                    entityMap.procurarEntidadePeloID(Familia.class, id_familia),
                    entityMap.procurarEntidadePeloID(Rectangulo.class, id_rectangulo),
                    entityMap.procurarEntidadePeloID(TipoTelha.class, id_tipo_de_telha),
                    entityMap.procurarEntidadePeloID(Estilo.class, id_estilo),
                    entityMap.procurarEntidadePeloID(DesenhoDinamico.class, id_desenho));
                    
            Field idField;
            try {
                idField = t.getClass().getSuperclass().getSuperclass().getDeclaredField("id");
                idField.setAccessible(true);

                idField.setInt(t, id);
                telha = t;
            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
                logger.logp(Level.SEVERE, TelhaGateway.class.getName(), "ProcurarComoMapa-onLinhaLida()", "Reflection API!", ex);
            }
        }
    }
    
    private class ProcurarComoMapa implements IDataBaseRow {
        private final IEntityMap entityMap;
        private final Map<Integer, Telha> mapa = new HashMap<>();

        ProcurarComoMapa(IEntityMap entityMap) {
            this.entityMap = entityMap;
        }
        
        public Map<Integer, Telha> getTelhas() {
            return mapa;
        }

        @Override
        public void onLinhaLida(ILinha linha) {
            int id = linha.getInt("id");
            int id_familia = linha.getInt("id_familia");
            int id_estilo = linha.getInt("id_estilo");
            int id_rectangulo = linha.getInt("id_rectangulo");
            int id_desenho = linha.getInt("id_desenho");
            int id_tipo_de_telha = linha.getInt("id_tipo_de_telha");

            Telha t = new Telha(
                    entityMap.procurarEntidadePeloID(Familia.class, id_familia),
                    entityMap.procurarEntidadePeloID(Rectangulo.class, id_rectangulo),
                    entityMap.procurarEntidadePeloID(TipoTelha.class, id_tipo_de_telha),
                    entityMap.procurarEntidadePeloID(Estilo.class, id_estilo),
                    entityMap.procurarEntidadePeloID(DesenhoDinamico.class, id_desenho));
            
            Field idField;
            try {
                idField = t.getClass().getSuperclass().getSuperclass().getDeclaredField("id");
                idField.setAccessible(true);

                idField.setInt(t, id);
                mapa.put(id, t);
            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
                logger.logp(Level.SEVERE, TelhaGateway.class.getName(), "ProcurarComoMapa-onLinhaLida()", "Reflection API!", ex);
            }
        }
    }
}
